﻿#include "MaterialTextureNodeModel.h"

#include "MaterialGraph/Pin/MaterialGraphPinModel.h"
#include "Object/NewObject.h"
#include "Asset/EngineDefaultPackage.h"

void RMaterialTextureNodeModel::FirstTimeInitializeObject()
{
    Texture= REngineDefaultPackage::Get()->GetEngineIcon();
    ParameterName = U"纹理1";

    //add RGBA output pin
    auto RGBAOutputPin = NewObject<RMaterialGraphPinModel>(this);
    RGBAOutputPin->ValueType= EMaterialGraphValueType::Vector4D;
    RGBAOutputPin->bIsOutput = true;
    Outputs.Add(RGBAOutputPin);

    //add RGB output pin
    auto RGBOutputPin = NewObject<RMaterialGraphPinModel>(this);
    RGBOutputPin->ValueType = EMaterialGraphValueType::Vector3D;
    RGBOutputPin->bIsOutput = true;
    Outputs.Add(RGBOutputPin);

    //add R output pin
    auto ROutputPin = NewObject<RMaterialGraphPinModel>(this);
    ROutputPin->ValueType = EMaterialGraphValueType::Vector1D;
    ROutputPin->bIsOutput = true;
    Outputs.Add(ROutputPin);

    //add G output pin
    auto GOutputPin = NewObject<RMaterialGraphPinModel>(this);
    GOutputPin->ValueType = EMaterialGraphValueType::Vector1D;
    GOutputPin->bIsOutput = true;
    Outputs.Add(GOutputPin);

    //add B output pin
    auto BOutputPin = NewObject<RMaterialGraphPinModel>(this);
    BOutputPin->ValueType = EMaterialGraphValueType::Vector1D;
    BOutputPin->bIsOutput = true;
    Outputs.Add(BOutputPin);

    //add A output pin
    auto AOutputPin = NewObject<RMaterialGraphPinModel>(this);
    AOutputPin->ValueType = EMaterialGraphValueType::Vector1D;
    AOutputPin->bIsOutput = true;
    Outputs.Add(AOutputPin);

    //add UV input pin
    auto UVInputPin = NewObject<RMaterialGraphPinModel>(this);
    UVInputPin->ValueType = EMaterialGraphValueType::Vector2D;
    UVInputPin->bIsOutput = false;
    Inputs.Add(UVInputPin);

}

CString RMaterialTextureNodeModel::GenerateExpression()
{
    assert(Texture && "纹理节点没有设置纹理");
    CString Result;

    CString UV;
    if(Inputs[0]->HasValidLink())
    {
        UV = Inputs[0]->GetValueExpression();
    }
    else
    {
        UV = U"inUV";
    }

    CString Color=U"vec4 TextureColor=texture(Texture2Ds["+CString(TextureIndex)+U"],"
        +UV
        + U");\n";

    CString Decalres;
    CString Assignment=Color;

    if(Outputs[0]->HasValidLink())
    {
        Decalres+=U"vec4 "+Outputs[0]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[0]->UniqueOutputPinName+U"=TextureColor;\n";
    }

    if(Outputs[1]->HasValidLink())
    {
        Decalres+=U"vec3 "+Outputs[1]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[1]->UniqueOutputPinName+U"=TextureColor.rgb;\n";
    }

    if(Outputs[2]->HasValidLink())
    {
        Decalres+=U"float "+Outputs[2]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[2]->UniqueOutputPinName+U"=TextureColor.r;\n";
    }

    if(Outputs[3]->HasValidLink())
    {
        Decalres+=U"float "+Outputs[3]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[3]->UniqueOutputPinName+U"=TextureColor.g;\n";
    }

    if(Outputs[4]->HasValidLink())
    {
        Decalres+=U"float "+Outputs[4]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[4]->UniqueOutputPinName+U"=TextureColor.b;\n";
    }

    if(Outputs[5]->HasValidLink())
    {
        Decalres+=U"float "+Outputs[5]->UniqueOutputPinName+U";\n";
        Assignment+= Outputs[5]->UniqueOutputPinName+U"=TextureColor.a;\n";
    }

    Result+=Decalres;
    Result+=
    U"{\n"
        +Assignment
    +U"}\n";

    return Result;
}

void RMaterialTextureNodeModel::SetTexture(TSharedObjectPtr<RTexture2D> InTexture)
{
    Texture = InTexture;
}

void RMaterialTextureNodeModel::CollectParameterAndTextures(TVector<float> &InOutFloatParameters, TVector<TSharedObjectPtr<RTexture2D>> &InOutTexture2Ds, TMap<CString, SMaterialParameterDescription> &InOutParameterDescriptions)
{
    assert(Texture && "纹理节点没有设置纹理");

    TextureIndex=InOutTexture2Ds.Num();
    InOutTexture2Ds.Add(Texture);

    if(bIsParameter)
    {
        SMaterialParameterDescription Description;
        Description.Type=EMaterialParameterType::Texture2D;
        Description.Offset=TextureIndex;
        InOutParameterDescriptions.Add(ParameterName,Description);
    }
}

void RMaterialTextureNodeModel::SetIsParameter(bool InIsParameter)
{
    if(bIsParameter==InIsParameter)
    {
        return;
    }

    bIsParameter=InIsParameter;

    OnIsParameterChanged.ExecuteIfBound();
}
